<script lang="ts" setup>
import type {
  OnActionClickParams,
  VxeTableGridOptions,
} from '#/adapter/vxe-table';

import { Page, useVbenDrawer } from '@vben/common-ui';
import { IconifyIcon, Plus } from '@vben/icons';
import { $t } from '@vben/locales';

import { MenuBadge } from '@vben-core/menu-ui';

import { Button, message } from 'ant-design-vue';
import { nextTick, ref } from 'vue';

import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { deleteMenu, getMenuList, SystemMenuApi } from '#/api/system/menu';

import { useColumns } from './data';
import Form from './modules/form.vue';

// 存储展开的节点ID
const expandedNodeIds = ref<string[]>([]);

// 收集所有展开的节点ID
const collectExpandedNodeIds = (nodes: any[]): string[] => {
  const ids: string[] = [];
  
  const traverse = (nodeList: any[]) => {
    for (const node of nodeList) {
      // 尝试多种方法检查节点是否展开
      let isExpanded = false;
      
      // 方法1: 使用isRowExpandByRow方法
      if (gridApi.grid?.isRowExpandByRow?.(node)) {
        isExpanded = true;
      }
      // 方法2: 检查节点是否有展开的子节点
      else if (node.children && node.children.length > 0) {
        // 获取表格DOM元素，检查展开状态
        try {
          // 尝试通过表格实例获取行元素
          const rowElem = gridApi.grid?.getRowNode?.(node);
          if (rowElem) {
            // 使用类型断言访问可能的DOM元素属性
            const rowElemAny = rowElem as any;
            const domElement = rowElemAny.elem || rowElemAny.$el || rowElemAny.element || rowElem;
            if (domElement) {
              const expandIcon = domElement.querySelector('.vxe-table--tree-btn');
              if (expandIcon && expandIcon.classList.contains('expand--active')) {
                isExpanded = true;
              }
            }
          }
        } catch (e) {
          // 忽略错误，使用备用方法
        }
      }
      
      if (isExpanded) {
        ids.push(node.id);
      }
      
      // 递归处理子节点
      if (node.children && node.children.length > 0) {
        traverse(node.children);
      }
    }
  };
  
  traverse(nodes);
  return ids;
};



const [FormDrawer, formDrawerApi] = useVbenDrawer({
  connectedComponent: Form,
  destroyOnClose: true,
});

const [Grid, gridApi] = useVbenVxeGrid({
  gridOptions: {
    columns: useColumns(onActionClick),
    height: 'auto',

    // 开启行选中功能
    rowConfig: {
      isCurrent: true, // 开启行选中功能
      isHover: false, // 开启鼠标悬停选中功能
      keyField: 'id', // 自定义行数据唯一主键的字段名（默认自动生成）
    },

    keepSource: true,
    pagerConfig: {
      enabled: false,
    },
    proxyConfig: {
      ajax: {
        query: async (_params) => {
          return await getMenuList();
        },
      },
    },
    toolbarConfig: {
      custom: true,
      export: false,
      refresh: { code: 'query' },
      zoom: true,
    },
    treeConfig: {
      parentField: 'pid',
      rowField: 'id',
      childrenField: 'children',
      transform: false,
      // 使用响应式方式绑定expandRowKeys
      get expandRowKeys() {
        return expandedNodeIds.value;
      },
    },
  } as VxeTableGridOptions,
});

function onActionClick({
  code,
  row,
}: OnActionClickParams<SystemMenuApi.SystemMenu>) {
  switch (code) {
    case 'append': {
      onAppend(row);
      break;
    }
    case 'delete': {
      onDelete(row);
      break;
    }
    case 'edit': {
      onEdit(row);
      break;
    }
    default: {
      break;
    }
  }
}

// 刷新表格数据
function onRefresh(options?: { nodeId?: string; isLocal?: boolean; isNewNode?: boolean; nodeData?: SystemMenuApi.SystemMenu }) {
  if (options?.isLocal && options.nodeId) {
    // 局部刷新：直接操作节点数据，不重新加载整个表格
    const currentData = gridApi.grid?.getTableData().fullData || [];
    
    if (options.isNewNode && options.nodeData) {
      // 新增节点：直接添加新节点到父节点
      const parentId = options.nodeData.pid;
      
      if (parentId) {
        // 添加子节点到父节点
        const findParentAndAddNode = (nodes: any[], parentId: string, newNode: any): any => {
          for (let i = 0; i < nodes.length; i++) {
            const node = nodes[i];
            if (node.id === parentId) {
              // 找到父节点，添加新节点
              if (!node.children) {
                node.children = [];
              }
              // 检查是否已存在该节点，避免重复添加
              const existingIndex = node.children.findIndex((child: any) => child.id === newNode.id);
              if (existingIndex === -1) {
                // 直接添加新节点，Vxe-Table 会自动计算缩进
                node.children.push(newNode);
                console.log(node);
              } else {
                // 如果已存在，则更新该节点
                Object.assign(node.children[existingIndex], newNode);
              }
              return node; // 返回父节点
            }
            if (node.children && node.children.length > 0) {
              const found = findParentAndAddNode(node.children, parentId, newNode);
              if (found) {
                return found; // 返回找到的父节点
              }
            }
          }
          return null;
        };
        
        // 添加新节点到父节点
        const parentNode = findParentAndAddNode(currentData, parentId, options.nodeData);
        
        // 只更新受影响的节点，而不是整个树
        if (parentNode) {
          // 使用updateData方法更新表格，不重新加载
          gridApi.grid?.updateData();
          
          // 确保父节点展开
          nextTick(() => {
            gridApi.grid?.setTreeExpand(parentNode, true);
            
            // 选中新增的节点
            setTimeout(() => {
              gridApi.grid?.setCurrentRow(options.nodeData);
            }, 300);
          });
        }
      } else {
        // 添加根节点
        // 直接添加新节点，Vxe-Table 会自动计算缩进
        currentData.push(options.nodeData);
        
        // 只更新新增的节点，而不是整个树
        gridApi.grid?.updateData();
        
        // 选中新增的根节点
        setTimeout(() => {
          gridApi.grid?.setCurrentRow(options.nodeData);
        }, 300);
      }
    } else {
      // 编辑节点：直接更新节点数据
      const findAndUpdateNode = (nodes: any[], nodeId: string, updatedNode: any): boolean => {
        for (let i = 0; i < nodes.length; i++) {
          const node = nodes[i];
          if (node.id === nodeId) {
            // 找到节点，更新该节点
            Object.assign(node, updatedNode);
            return true;
          }
          if (node.children && node.children.length > 0) {
            if (findAndUpdateNode(node.children, nodeId, updatedNode)) {
              return true;
            }
          }
        }
        return false;
      };
      
      // 从API获取最新节点数据
      getMenuList().then((newData) => {
        // 从新数据中找到对应节点
        const findNodeInNewData = (nodes: any[], nodeId: string): any => {
          for (const node of nodes) {
            if (node.id === nodeId) {
              return node;
            }
            if (node.children && node.children.length > 0) {
              const found = findNodeInNewData(node.children, nodeId);
              if (found) return found;
            }
          }
          return null;
        };
        
        const updatedNode = findNodeInNewData(newData, options.nodeId!);
        if (updatedNode) {
          // 更新当前数据中的节点
          findAndUpdateNode(currentData, options.nodeId!, updatedNode);
          
          // 使用updateData方法更新表格，不重新加载
          gridApi.grid?.updateData();
          
          // 选中编辑的节点
          setTimeout(() => {
            const findNodeInCurrentData = (nodes: any[], nodeId: string): any => {
              for (const node of nodes) {
                if (node.id === nodeId) {
                  return node;
                }
                if (node.children && node.children.length > 0) {
                  const found = findNodeInCurrentData(node.children, nodeId);
                  if (found) return found;
                }
              }
              return null;
            };
            
            const currentNode = findNodeInCurrentData(currentData, options.nodeId!);
            if (currentNode) {
              gridApi.grid?.setCurrentRow(currentNode);
            }
          }, 300);
        } else {
          // 如果找不到节点，重新加载整个树
          gridApi.query();
        }
      }).catch((error) => {
        console.error('获取菜单列表失败:', error);
        // 出错时重新加载整个树
        gridApi.query();
      });
    }
  } else {
    // 整体刷新
    gridApi.query();
  }
}

function onEdit(row: SystemMenuApi.SystemMenu) {
  formDrawerApi.setData(row).open();
}
function onCreate() {
  formDrawerApi.setData({}).open();
}
function onAppend(row: SystemMenuApi.SystemMenu) {
  formDrawerApi.setData({ pid: row.id }).open();
}
const expandAll = () => {
  gridApi.grid?.setAllTreeExpand(true);
};
const collapseAll = () => {
  gridApi.grid?.setAllTreeExpand(false);
};
function onDelete(row: SystemMenuApi.SystemMenu) {
  const hideLoading = message.loading({
    content: $t('ui.actionMessage.deleting', [row.name]),
    duration: 0,
    key: 'action_process_msg',
  });
  
  // 在删除前保存当前展开状态和节点信息
  const currentData = gridApi.grid?.getTableData().fullData || [];
  expandedNodeIds.value = collectExpandedNodeIds(currentData);
  
  deleteMenu(row.id)
    .then(() => {
      message.success({
        content: $t('ui.actionMessage.deleteSuccess', [row.name]),
        key: 'action_process_msg',
      });
      
      // 在删除前保存当前展开状态和节点信息
      const currentData = gridApi.grid?.getTableData().fullData || [];
      const deletedNode = { ...row };
      expandedNodeIds.value = collectExpandedNodeIds(currentData);
      
      // 删除后刷新数据
      getMenuList().then((newData) => {
        // 使用reloadData而不是loadData，这样可以更好地保持树形状态
        gridApi.grid?.reloadData(newData);
        
        // 使用nextTick确保DOM更新后再恢复展开状态
      nextTick(() => {
        // 使用双重nextTick确保DOM完全更新
        nextTick(() => {
          // 遍历所有需要展开的节点ID，并展开它们
          expandedNodeIds.value.forEach(nodeId => {
            const row = gridApi.grid?.getRowById?.(nodeId);
            if (row) {
              gridApi.grid?.setTreeExpand(row, true);
            }
          });
          
          // 如果删除的是父节点，尝试选中其第一个子节点或父节点
          setTimeout(() => {
            if (deletedNode.children && deletedNode.children.length > 0) {
              // 如果删除的节点有子节点，选中第一个子节点
              const firstChild = deletedNode.children[0];
              gridApi.grid?.setCurrentRow(firstChild);
            } else if (deletedNode.pid) {
              // 如果删除的节点是子节点，选中其父节点
              const findParentNode = (nodes: any[], parentId: string): any => {
                for (const node of nodes) {
                  if (node.id === parentId) {
                    return node;
                  }
                  if (node.children && node.children.length > 0) {
                    const found = findParentNode(node.children, parentId);
                    if (found) return found;
                  }
                }
                return null;
              };
              
              const parentNode = findParentNode(newData, deletedNode.pid);
              if (parentNode) {
                gridApi.grid?.setCurrentRow(parentNode);
              }
            }
          }, 300);
        });
      });
      }).catch((error) => {
        console.error('获取菜单列表失败:', error);
        // 出错时重新加载整个树
        gridApi.query();
      });
    })
    .catch(() => {
      hideLoading();
    });
}
</script>

<template>
  <Page auto-content-height>
    <FormDrawer @success="(options: { nodeId?: string; isLocal?: boolean; isNewNode?: boolean; nodeData?: SystemMenuApi.SystemMenu }) => onRefresh(options)" />
    <Grid>
      <template #toolbar-tools>
        <Button class="mr-2" type="primary" @click="expandAll">
          展开全部
        </Button>
        <Button class="mr-2" type="primary" @click="collapseAll">
          折叠全部
        </Button>
        <Button
          type="primary"
          @click="onCreate"
          v-permission="'system:menu:create'"
        >
          <Plus class="size-5" />
          {{ $t('ui.actionTitle.create', [$t('system.menu.name')]) }}
        </Button>
      </template>
      <template #title="{ row }">
        <div class="flex w-full items-center gap-1">
          <div class="size-5 flex-shrink-0">
            <IconifyIcon
              v-if="row.type === 'button'"
              icon="carbon:security"
              class="size-full"
            />
            <IconifyIcon
              v-else-if="row.meta?.icon"
              :icon="row.meta?.icon || 'carbon:circle-dash'"
              class="size-full"
            />
          </div>
          <span class="flex-auto">{{ $t(row.meta?.title) }}</span>
          <div class="items-center justify-end"></div>
        </div>
        <MenuBadge
          v-if="row.meta?.badgeType"
          class="menu-badge"
          :badge="row.meta.badge"
          :badge-type="row.meta.badgeType"
          :badge-variants="row.meta.badgeVariants"
        />
      </template>
    </Grid>
  </Page>
</template>

<style lang="scss" scoped>
.menu-badge {
  top: 50%;
  right: 0;
  transform: translateY(-50%);

  & > :deep(div) {
    padding-top: 0;
    padding-bottom: 0;
  }
}
</style>
